import csv
import datetime
import os
import sys
import time

from sqlalchemy import Column, ForeignKey, Index, Integer, String, DateTime, Date, Time, Float, Enum, Boolean
from sqlalchemy.orm import relation, backref, sessionmaker
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta

class Entity(object):

    @classmethod
    def get_db_key(cls):
        return cls.__module__.split('.')[2]

    @property
    def db_key(self):
        return self.get_db_key()

    def get_column_default(self, key):
        """Get default set in SQLA table (NOT server default)."""
        # XXX: Is this method really necessary?
        default = self.__table__.columns.get(key).default
        if not default:
            return None
        return default.arg

    def _fixup(self): 
        '''(over-ride me): _fixup is called after creating an object via dictionary '''

    @classmethod
    def set_schema(cls, schema):
        cls.__table__.schema = schema

    @classmethod
    def get_filename(cls, ext='txt'):
        return '%s.%s' % (cls.__tablename__, ext)

    @classmethod
    def get_filepath(cls, directory='.', default='no file found'):
        ret_val = default 
        for x in ('txt', 'csv', 'doc'):
            file = cls.get_filename(x)
            file_path = os.path.join(directory, file)
            if os.path.exists(file_path):
                ret_val = file_path
                break

        return ret_val

    @classmethod
    def make_record(cls, row):
        # clean dict
        for k, v in row.items():
            if isinstance(v, basestring):
                v = v.strip()
            if (k not in cls.__table__.c):
                del row[k]
            elif not v:
                row[k] = None
            elif k.endswith('date'):
                row[k] = datetime.datetime.strptime(v, '%Y%m%d').date()

        return row

    @classmethod
    def from_dict(cls, attrs):
        clean_dict = cls.make_record(attrs)
        c = cls(**clean_dict)
        c._fixup()
        return c

    @classmethod
    def load(cls, engine, directory='.', file=None):
        records = []
        if(file is None):
            file_path = cls.get_filepath(directory)
        else:
            file_path = os.path.join(directory, file)

        if os.path.exists(file_path) == False:
            print "Could not find file", file_path
        else:
            print "Loading file", file_path
            file = open(file_path, 'r')
            reader = csv.DictReader(file)
            table = cls.__table__
            engine.execute(table.delete())
            Session = sessionmaker(bind=engine)
            session = Session()
            i = 0
            for row in reader:
                records.append(cls.from_dict(row))
                i += 1
                # commit every 10,000 records to the database to manage memory usage
                if i >= 10000:
                    session.add_all(records)
                    session.flush()
                    session.commit()

                    records = []
                    i = 0
            if len(records) > 0:
                session.add_all(records)
                session.flush()
                session.commit()
                session.flush()
                session.close()

            file.close()


class EntityMeta(DeclarativeMeta):
    """Place holder."""

Base = declarative_base(cls=Entity)
""":class:`Base` will be a subclass of :class:`Entity`."""
